package dao;

import interfaces.DAOInterface;
import interfaces.IdAutoIncrement;

import java.lang.reflect.ParameterizedType;
import java.util.List;

public class DAORedeHoteisHilton<T> implements DAOInterface<T> {
	
	/**
	 * Usa o nome da classe do objeto que vai ser persistido para gerar o Id automaticamente e depois adiciona o objeto a sua respectiva lista no container.
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void persist(T obj) {
		Class<T> type = (Class<T>) ((ParameterizedType) this.getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
		if(obj instanceof IdAutoIncrement)
			((IdAutoIncrement) obj).setId(Container.getInstance().gerarId(obj.getClass().getName()));
		
		Container.getInstance().getList(type.getName()).add(obj);
	}
	
	/**
	 * Usa o nome da classe do objeto a ser removido para remover o objeto da sua respectiva lista no container.
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void remove(T obj) {
		Class<T> type = (Class<T>) ((ParameterizedType) this.getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
		Container.getInstance().getList(type.getName()).remove(obj);
	}
	
	/**
	 * Atualiza o objeto na sua respectiva lista no container usando o Id do objeto.
	 * A lista � escolhida atrav�s do nome da classe.
	 * @return O objeto que foi atualizado
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public T merge(T obj) {
		List lista = Container.getInstance().getList(obj.getClass().getName());
		int index = lista.indexOf( findById( ((IdAutoIncrement) obj).getId() ) );
		lista.set(index, obj);

		return null;
	}
	
	/**
	 * Atualiza o objeto na memoria de acordo com o mesmo objeto no arquivo.
	 */
	@Override
	public void refresh(T obj) {
		/*
		 * Implementar caso precise.
		 */
	}
	
	/**
	 * Salva o container no arquivo.
	 */
	public void commit() {
		Container.getInstance().saveFile();
	}
	
	/**
	 * Sobrescreve o container da memoria pelo container do arquivo.
	 */
	public void rollback() {
		Container.getInstance().openFile();
	}
	
	/**
	 * Retorna todos os objetos do tipo do DAO
	 * @return Lista com todos os objetos do tipo da classe parametrizada no DAO
	 */
	@SuppressWarnings("unchecked")
	public List<T> findAll(){
		Class<T> type = (Class<T>) ((ParameterizedType) this.getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
		return Container.getInstance().getList(type.getName());
	}
	
	/**
	 * Encontra um objeto pelo Id
	 * @param id Id do objeto que deseja achar
	 * @return O objeto encontrado. Retorna null se o objeto n�o existir na lista.
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public T findById(int id) {
		Class<T> type = (Class<T>) ((ParameterizedType) this.getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
		List lista = Container.getInstance().getList(type.getName());
		for(Object obj : lista) {
			if(((IdAutoIncrement) obj).getId() == id)
				return (T) obj;
			
		}
		
		return null;
	}
	
	/**
	 * Encontrado o ultimo objeto persistido
	 * @return O ultimo objeto persistido
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public T findLast() {
		Class<T> type = (Class<T>) ((ParameterizedType) this.getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
		List lista = Container.getInstance().getList(type.getName());
		return (T)lista.get(lista.size() - 1);
		
	}
	
}
